package Service

import (
	cache "ShortLink/Cache"
	web "ShortLink/Core/Web"
	entity "ShortLink/Data/Entity"
	models "ShortLink/Data/Models"
	repository "ShortLink/Repository"
	intHelper "ShortLink/Utils/IntHelper"
	"ShortLink/Utils/Random"
	"log"
	"net/http"
	"regexp"
	"time"

	"github.com/gin-gonic/gin"
)

var segmentLength int = 4
var segmentLengths []int = []int{4, 5, 6}

func GoLink(c *gin.Context) {
	segment := c.Param("segment")
	if !regexp.MustCompile(`[a-zA-Z0-9]+`).MatchString(segment) || intHelper.Continue(segmentLengths, len(segment)) {
		web.Success(c)
		return
	}
	repository.Extension(segment, time.Now().AddDate(1, 0, 0))
	link := cache.GetLink(segment)
	if len(link) == 0 {
		web.ParamError(c)
		return
	}
	http.Redirect(c.Writer, c.Request, link, http.StatusFound)
}

func AddLink(c *gin.Context) {
	var addInfo models.AddLinkRequest
	if err := c.ShouldBind(&addInfo); err != nil {
		log.Fatal(err)
		web.ParamError(c)
		return
	}

	if len(addInfo.JumpLink) == 0 {
		web.ParamError(c, "跳转内容不能为空")
		return
	}

	minute := time.Minute * time.Duration(addInfo.Duration)
	linkInfo := new(entity.LinkInfo)
	linkInfo.JumpLink = addInfo.JumpLink
	linkInfo.CreateTime = time.Now()
	linkInfo.ExpiryTime = time.Now().Add(minute)
	linkInfo.Segment = Random.RandomString(segmentLength)
	if repository.Add(linkInfo) {
		cache.SetLink(linkInfo.Segment, linkInfo.JumpLink, minute)
		web.Success(c)
		return
	}
	web.ServerError(c)
}

func EditLink(c *gin.Context) {
	segment := c.Param("segment")
	if !regexp.MustCompile(`[a-zA-Z0-9]+`).MatchString(segment) || intHelper.Continue(segmentLengths, len(segment)) {
		web.ParamError(c)
		return
	}
	var editInfo models.EditLinkRequest
	if err := c.ShouldBind(&editInfo); err != nil {
		log.Fatal(err)
		web.ParamError(c)
		return
	}

	if len(editInfo.JumpLink) == 0 {
		web.ParamError(c, "跳转内容不能为空")
		return
	}

	link := repository.QueryBySegment(segment)
	if link == nil {
		web.NotExist(c)
		return
	}

	rowCount := repository.EditJumpLink(segment, editInfo.JumpLink)
	if rowCount == 0 { //影响行数为0，说明数据不存在
		web.NotExist(c)
		return
	}
	t := time.Now()
	if t.After(link.ExpiryTime) { //当前时间在过期时间之前
		dur := link.ExpiryTime.Sub(t)
		cache.SetLink(link.Segment, editInfo.JumpLink, dur)
	}

	web.Success(c)
}

func DelLink(c *gin.Context) {
	segment := c.Param("segment")
	if !regexp.MustCompile(`[a-zA-Z0-9]+`).MatchString(segment) || intHelper.Continue(segmentLengths, len(segment)) {
		web.ParamError(c)
		return
	}

	rowCount := repository.Delete(segment)
	if rowCount > 0 {
		cache.DelLink(segment)
	}
	web.Success(c)
}
